/**
 * 
 */
package jvs.peer.xmpp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import jvs.peer.io.File;
import jvs.peer.io.Lifecycle;
import jvs.peer.net.PeerAddress;
import jvs.peer.net.PeerServerSocket;
import jvs.peer.util.Log;

/**
 * @author qiangli
 * 
 */
public class XmppFileServer implements Lifecycle {
	private class ServiceThread extends Thread {
		private Socket socket = null;

		public ServiceThread(Socket socket) {
			super("XMPP File Service");
			this.socket = socket;
		}

		public void run() {
			try {

				BufferedReader in = new BufferedReader(new InputStreamReader(
						socket.getInputStream()), File.BUFSIZE);
				// parse
				StringBuilder sb = new StringBuilder();
				String line = null;
				while ((line = in.readLine()) != null) {
					sb.append(line);
					sb.append("\r\n");
					if (line.equalsIgnoreCase("bye")) {
						break;
					}
				}
				//execute single command
				OutputStream out = socket.getOutputStream();
				XmppFileShell sh = getShell(socket);
				sh.setOut(out);
				String cmd = sb.toString();
				sh.parse(cmd);
				//
				//log(cmd);
				//
				out.close();
				in.close();
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
			}
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private static int serverId = 0;
	
	private static Map<String, XmppFileShell> shells = new HashMap<String, XmppFileShell>();
	private int instanceId = 0;
	private boolean running;
	private ServerSocket listen;
	private Thread server;

	public XmppFileServer() throws IOException {
	}

	synchronized private static XmppFileShell getShell(Socket socket) {
		PeerAddress remoteAddr = (PeerAddress) socket.getRemoteSocketAddress();
		String key = remoteAddr.getId() + "/" + remoteAddr.getResource();
		XmppFileShell sh = shells.get(key);
		if (sh == null) {
			sh = new XmppFileShell((PeerAddress) socket
					.getLocalSocketAddress(), remoteAddr);
			sh.init();
		}
		return sh;
	}

	public void service() {
		while (running) {
			try {
				instanceId++;
				String id = serverId + ":" + instanceId;
				
				if (Log.DEBUG) {
					Log.log(this, "Server instance [" + id + "] Ready.");
				}
				Socket s = listen.accept();

				Thread t = new ServiceThread(s);

				t.start();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void startup() throws IOException {
		running = true;
		server = new Thread() {
			public void run() {
				service();
			}
		};
		server.start();
	}

	public void shutdown() {
		running = false;
		server.interrupt();
		server = null;
	}

	public void init(Properties props) throws Exception {
		listen = new PeerServerSocket();
		//log("XMPP File Server by Li, Qiang\r\n");
	}

	public void release() {
		listen = null;
	}
}
